package com.allwees.bs.c.module.order.context.processor;

import com.allwees.bs.c.module.ops.service.CashActiveDefUseService;
import com.allwees.bs.c.module.order.entity.OrderEntity;
import com.allwees.bs.c.module.order.entity.OrderItemEntity;
import com.allwees.bs.c.module.order.mq.event.OrderItemApplyRefundEvent;
import com.allwees.bs.c.module.order.repository.OrderItemRepository;
import com.allwees.bs.c.module.order.repository.OrderRefundRepository;
import com.allwees.bs.c.module.order.repository.OrderRepository;
import com.allwees.bs.c.module.order.req.OrderApplyRefundReq;
import com.allwees.bs.c.module.order.service.IOrderRefundService;
import com.allwees.bs.c.module.product.service.ProductService;
import com.allwees.bs.core.model.constant.CacheName;
import com.allwees.bs.core.model.order.wf.order.EOrderAction;
import com.allwees.bs.core.model.order.wf.order.EOrderItemAction;
import com.allwees.bs.core.model.order.wf.order.EOrderItemState;
import com.allwees.bs.core.model.order.wf.refund.ERefundState;
import com.allwees.bs.core.modelbase.constant.ResultEnum;
import com.allwees.bs.core.modelbase.exception.BusinessException;
import com.allwees.bs.module.base.refund.AbstractRefundService;
import com.allwees.core.cache.RedisUtil;
import com.allwees.core.mq.rabbitmq.MqUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

@Slf4j
@Service
public class OrderRefundPostProcessor extends AbstractRefundService<OrderItemEntity> {

    @Autowired
    private IOrderRefundService orderRefundService;
    @Autowired
    private OrderItemRepository orderItemRepository;
    @Autowired
    private OrderRefundRepository orderRefundRepository;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderPostProcessor orderPostProcessor;
    @Autowired
    private CashActiveDefUseService cashActiveDefUseService;

    @Autowired
    private ProductService productService;

    @Override
    protected void check(OrderItemEntity orderItem, String userUuid) {
        if (orderItem == null) {
            throw BusinessException.getInstance(ResultEnum.NOT_FOUND);
        }
        if (orderItem.getRefundAble() != null && !orderItem.getRefundAble()) {
            throw BusinessException.getInstance(ResultEnum.DATA_NO_PRIVILEGE);
        }
        if (!orderItem.getUserUuid().equals(userUuid)) {
            throw BusinessException.getInstance(ResultEnum.DATA_NO_PRIVILEGE);
        }

        if (!(EOrderItemState.WAIT_SHIP.equals(orderItem.getState()) && !orderItem.getCanShipping()) && !EOrderItemState.RECEIVED.equals(orderItem.getState())) {
            throw BusinessException.getInstance(ResultEnum.ORDER_CANNOT_REQUEST_REFUND);
        }

        if (System.currentTimeMillis() > orderItem.getRefundExpiredAt().getTime()) {
            throw BusinessException.getInstance(ResultEnum.ORDER_CANNOT_REQUEST_REFUND);
        }
    }

    @Override
    protected OrderItemEntity checkByUuid(String orderItemUuid) {
        return orderItemRepository.getByUuid(orderItemUuid);
    }

    @Override
    protected boolean isWaitShip(OrderItemEntity orderItem) {
        return orderItem.getState().equals(EOrderItemState.WAIT_SHIP);
    }

    @Override
    protected void doRefunded(OrderItemEntity orderItem, Object req) {
        EOrderItemAction action = EOrderItemAction.USER_REQUEST_REFUND_WITH_WAIT_SHIP;
        orderItem.signal(action);
        //记录o_order_refund表
        after(orderItem, req);

        orderPostProcessor.userRefundProcess(true, orderItem.getOrderUuid(), orderItem.getUuid());
        doOrderItemCashRefunded(orderItem.getUuid());
        //增加库存
        productService.addInventory(orderItem.getSkuUuid(), orderItem.getQuantity());
        //refundLogActionUtil.logAction(orderItem,usersRepository.checkIsInfluencer(orderItem.getUserUuid()));
        refundProductLimitNum(orderItem);
    }

    private void refundProductLimitNum(OrderItemEntity orderItem) {
        Integer numPerUser = RedisUtil.hget(CacheName.PROD_PRODUCT_MODEL_BY_UUID, orderItem.getProductUuid());
        if (numPerUser == null || numPerUser == 0) {
            return;
        }
        Integer buyedNum = RedisUtil.hget(CacheName.USER_BUY_PRODUCT_NUM, orderItem.getUserUuid() + ":" + orderItem.getProductUuid());
        log.info("======refundProductLimitNum=======userUuid:{},has buyed num:{}, productUuid:{}", orderItem.getUserUuid(), buyedNum, orderItem.getProductUuid());
        if (buyedNum == null) {
            buyedNum = 0;
        }
        buyedNum = buyedNum - orderItem.getQuantity();
        RedisUtil.hset(CacheName.USER_BUY_PRODUCT_NUM, orderItem.getUserUuid() + ":" + orderItem.getProductUuid(), buyedNum);
    }

    @Override
    protected void updateWithApply(OrderItemEntity orderItem, Object req) {
        EOrderItemAction action = EOrderItemAction.USER_REQUEST_REFUND_WITH_RECEIVED;
        orderItem.setApplyRefundAt(new Date());
        orderItem.signal(action);
        after(orderItem, req);
        MqUtil.send(new OrderItemApplyRefundEvent(orderItem.getUuid()));
    }

    private void after(OrderItemEntity orderItem, Object req) {
        orderItemRepository.save(orderItem);
        orderRefundService.apply((OrderApplyRefundReq) req);
    }

    @Override
    protected boolean isAllRefunded(String orderUuid) {
        OrderEntity order = orderRepository.getByUuid(orderUuid);
        int orderRefundCount = orderRefundRepository.getCountByOrderUuidAndState(orderUuid, ERefundState.COMPLETED);
        return !(orderRefundCount == 0 || orderRefundCount < order.getQuantity());
    }


    @Override
    protected void doOrderRefunded(String orderUuid, String orderItemUuid) {
        OrderEntity order = orderRepository.getByUuid(orderUuid);
        order.signal(EOrderAction.SYSTEM_CLOSE_BY_ALL_REFUND);
        orderRepository.save(order);

        //cashActiveDefUseService.refunded(order.getUserUuid(), order.getUuid(), order.getAmtCash());
    }

    @Override
    protected void doOrderItemCashRefunded(String orderItemUuid) {
        OrderItemEntity orderItem = orderItemRepository.getByUuid(orderItemUuid);
        cashActiveDefUseService.refunded(orderItem.getUserUuid(), orderItem.getOrderUuid(), orderItem.getAmtCashSku());
    }
}
